<?php

/**
 * 验证码相关接口
 * 目的：短信业务逻辑从sms接口中独立出来
 * Created by PhpStorm.
 * User: 章利桂
 * Date: 2016/8/29
 * Time: 12:04
 */
class verifyCodeModel
{
    public function __construct(& $base)
    {
        $this->base = $base;
        $this->db = & $this->base->db;
        $this->redis = & $this->base->redis;
    }

    /**
     * 云测平台短信发送
     */
    public function sendCodeBytestinSMS($mobile, $flag) {
        if(empty($mobile)) {
            return false;
        }
        if(!$this->_checkCount($mobile, $this->base->client)){//一个账号在5小时内只能请求5次，超过5次，锁定5小时
            return -1;//验证码已达上限
        }
        $boolCanSend = $this->checkVerifyCodeForTime($mobile); //查询2分钟内是否有记录
        if ($boolCanSend == false) {
            return -2;//频繁操作
        }
        include FILE.'lib/sms.class.php';
        $sms = new sms();
        $verifyCode = mt_rand(1021,9999);
        $resultCode =  $sms->testinSMSNew($mobile, $verifyCode, $flag);
        if($resultCode == 1000) { //写入表记录
            $this->addVerifyCode($mobile, $verifyCode);
        }
        return $resultCode;
    }
    /**
     * 查询2分钟内发送状态
     * @param $mobile
     * @param $flag  1 找回密码 0 更改手机、注册和手机绑定…… (预留字段 以后最好区分业务)
     * @return bool
     */
    public function checkVerifyCodeForTime($mobile, $flag=0) {
        //查询redis是否有记录
        $repeatSendKey = REDIS_PREFIX.'_repeatSend_'.$mobile;
//        if (!$this->redis->exists($repeatSendKey)) { //第一次 没有记录 查询表记录
//            $startTime = bcsub(time(),2*60);
//            $arrInfo = $this->db->getRow("select * from r_mobile_code
//                            where mobile='$mobile'
//                            and send_time >=$startTime
//                            AND verify_time=0");
//            if ($arrInfo) {
//                //重新写入redis缓存
//                $time  = bcsub(2*60,bcsub(time(),$arrInfo['send_time']));//剩余时间
//                $this->redis->setex($repeatSendKey,$time,1);
//                return false;
//            }
//            $this->redis->set($repeatSendKey,0);//确实没有记录
//            return true;
//        }
       // $this->base->load('log')->writeLog('api','checkVerifyCodeForTime-1:'.date('Y-m-d H:i:s').' result:'.var_export($repeatSendKey,true).PHP_EOL,'print-'.date('Y-m-d').'.log');
        if ($this->redis->get($repeatSendKey)) {
            return false;
        }
        return true;
    }

    /**
     * 记录验证码
     */
    public function addVerifyCode($mobile, $verify_code) {
        $repeatSendKey = REDIS_PREFIX.'_repeatSend_'.$mobile;
        $validGetKey  = REDIS_PREFIX.'_validGet_'.$mobile;
        $this->redis->setex($repeatSendKey, 2*60, 1);//2分钟不能重复发送
        $this->redis->setex($validGetKey, 10*60, $verify_code);//10分钟有效

        $send_time = time();
        $params = compact('mobile', 'verify_code', 'send_time');
        //$this->base->load('log')->writeLog('api','addVerifyCode-1:'.date('Y-m-d H:i:s').' result:'.var_export($params,true).PHP_EOL,'print-'.date('Y-m-d').'.log');
        $result = $this->db->insertRow("r_mobile_code", $params);
        //$this->base->load('log')->writeLog('api','addVerifyCode-2:'.date('Y-m-d H:i:s').' result:'.var_export($result,true).PHP_EOL,'print-'.date('Y-m-d').'.log');
        if (!$result) {
            return false;
        }
        return true;
    }

    /**
     * 校验验证码
     */
    public function checkCode($mobile, $code) {
        $validGetKey  = REDIS_PREFIX.'_validGet_'.$mobile;
        //$this->base->load('log')->writeLog('api','checkCode-1:'.date('Y-m-d H:i:s').' result:'.var_export($validGetKey,true).PHP_EOL,'print-'.date('Y-m-d').'.log');
        if (!$this->redis->get($validGetKey)) {
            //$this->base->load('log')->writeLog('api','checkCode-2:'.date('Y-m-d H:i:s').' result:'.var_export($this->redis->get($validGetKey),true).PHP_EOL,'print-'.date('Y-m-d').'.log');
            return 1004;
        }
        if ($this->redis->get($validGetKey) != $code) {
            //$this->base->load('log')->writeLog('api','checkCode-2:'.date('Y-m-d H:i:s').' result:'.var_export($this->redis->get($validGetKey),true).PHP_EOL,'print-'.date('Y-m-d').'.log');
            return 1102;
        }
       // $this->base->load('log')->writeLog('api','checkCode-2:'.date('Y-m-d H:i:s').' result:'.var_export($this->redis->get($validGetKey),true).'-code:'.$code.PHP_EOL,'print-'.date('Y-m-d').'.log');
        return true;
    }

    /**
     * 操作成功后，，更新验证码表 ，删除redis缓存
     */
    public function saveVerifyTime($mobile, $code) {
        $validGetKey  = REDIS_PREFIX.'_validGet_'.$mobile;
        //删除10分钟设置的redis的有效Code
        $this->redis->del($validGetKey);
        //更新验证码表
        $time = time();
        $startTime = bcsub($time,10*60);//10分钟内有效的验证码
        $result = $this->db->update("update r_mobile_code set verify_time= $time where mobile='$mobile' and verify_code='$code' and send_time >= $startTime ");
        return true;
    }

    /**
     * 一个账号在5小时内只能请求5次，超过5次，锁定5小时
     * @param $phone
     * @param $client
     * @return bool
     */
    private function _checkCount($phone, $client) {
        $ip = common::getip(true);
        $ipKey = REDIS_PREFIX.'ip'.$ip;
        $phoneKey = REDIS_PREFIX.'phone'.$phone;
        $clientKey = REDIS_PREFIX.'client'.$client;
        $forbidKey = REDIS_PREFIX."forbid".$phone;
        if($this->redis->get($forbidKey)){
            return false;
        }
        $ipCount = intval($this->redis->get($ipKey));
        $phoneCount = intval($this->redis->get($phoneKey));
        $clientCount = intval($this->redis->get($clientKey));
        if($ipCount >= 5 || $phoneCount >= 5 || $clientCount >= 5){
            $this->redis->setex($forbidKey,5*3600,1);
            return false;
        }
        if(!$this->redis->exists($phoneKey)){
            $time = 5*3600;
            $this->redis->setex($ipKey,$time,1);
            $this->redis->setex($phoneKey,$time,1);
            $this->redis->setex($clientKey,$time,1);
        }else{
            $this->redis->incr($ipKey);
            $this->redis->incr($phoneKey);
            $this->redis->incr($clientKey);
        }
        return true;
    }
}